
/*
 * 文件名：CesiumDX
 * 作者：胡晓洋
 * 描述：用于3dtiles加载，优化，删除，等功能
 * 修改时间：2021/11/02
*/

// const tilesArr = [
//     {
//       id: 1,
//       tileUrl: "http://127.0.0.1:8080/3Dtiles/tileset.json",
//       name: "大雁塔模型",
//       show: true,
//     },
//   ];


export default class DxTiles {
    constructor(options) {
        this.viewer = options.viewer;
        this.tilesLit = []; // 保存tiles属性信息
        this.tileindex = 0; // 轮询索引
        this.DataSource = null;
        this.activeSource = null; // 要素类
        this.maxtrixObj = { sc: 10.0, lon: 0, lat: 0, ht: 0, rx: 0, ry: 0, rz: 0, ap: 1.0, tileModel: null };
        this.managerCollection = null;
        this.init()
    }
    init() {
        this.managerCollection = new Cesium.PrimitiveCollection();
        this.viewer.scene.primitives.add(this.managerCollection);
    }
    calculatedHeight(positions, properties, geometry) {
        return new Promise((resolve, reject) => {
            Cesium.when(new Cesium.sampleTerrain(this.viewer.terrainProvider, 11, [positions]), (updatedPositions) => {
                const coordinate = updatedPositions[0];
                properties.coordinate = [geometry.coordinates[0], geometry.coordinates[1], coordinate.height]
                // const maxtrixObj = { lon: geometry.coordinates[0], lat: geometry.coordinates[1], ht: coordinate.height };
                properties.maxtrixObj = { sc: 1.0, lon: geometry.coordinates[0], lat: geometry.coordinates[1], ht: coordinate.height, rx: 0, ry: 0, rz: 0, ap: 1.0, tileModel: null };
                // Object.assign(JSON.parse(JSON.stringify(this.maxtrixObj)), { ...maxtrixObj })
                properties.currentModel = null
                resolve(properties)
                // 绘制3dtiles
                // this.drawElementTiles(properties)
            });
        })
    }
    addEleAllTiles(target) {
        this.removePrimitive(target.name);
        const proList = [];
        // this.viewer.scene.globe.depthTestAgainstTerrain = true;
        // 根据要素名称查找datasource
        this.activeSource = CesiumDX.DXSourceOptions.EleOptions.find(ele => ele.name === target.name) || null;
        // let i = this.tileindex = 0
        for (let i = 0; i < target.features.length; i++) {
            const geometry = target.features[i].geometry;
            if (geometry.type === "Point") {
                var positions = Cesium.Cartographic.fromDegrees(geometry.coordinates[0], geometry.coordinates[1]);
                const properties = target.features[i].properties;
                // 如果有重复，剔除
                const beIn = this.activeSource.listServer.findIndex(item => item.id === properties.id)
                if (beIn !== -1) return
                proList.push(this.calculatedHeight(positions, properties, geometry))
            }
        }
        Promise.all(proList).then(resp => {
            resp.forEach(properties => {
                this.activeSource.listServer.push(properties)
            })
            this.drawElementTiles(this.activeSource.listServer[this.tileindex])
        })
    }
    drawElementTiles(target) {
        debugger
        // this.viewer.scene.globe.depthTestAgainstTerrain = true;
        target.tileModel = this.viewer.scene.primitives.add(
            new Cesium.Cesium3DTileset({
                url: target.modelUrl,// Cesium.IonResource.fromAssetId(75343), //  
                skipLevelOfDetail: true,
                baseScreenSpaceError: 1024,
                skipScreenSpaceErrorFactor: 16,
                skipLevels: 1,
                immediatelyLoadDesiredLevelOfDetail: false,
                loadSiblings: false,
                cullWithChildrenBounds: true,
                dynamicScreenSpaceError: true,
                maximumScreenSpaceError: 16
            })
        )
        target.tileModel.readyPromise
            .then((currentModel) => {
                target.currentModel = currentModel
                this.viewer.zoomTo(currentModel);
                var selected = {
                    feature: undefined,
                    originalColor: new Cesium.Color(),
                };
                var selectedEntity = new Cesium.Entity();
                var highlighted = {
                    feature: undefined,
                    originalColor: new Cesium.Color(),
                };
                this.viewer.screenSpaceEventHandler.setInputAction(movement => {
                    // If a feature was previously selected, undo the highlight
                    if (Cesium.defined(selected.feature)) {
                        selected.feature.color = selected.originalColor;
                        selected.feature = undefined;
                    }
                    // Pick a new feature
                    var pickedFeature = this.viewer.scene.pick(movement.position);
                    if (!Cesium.defined(pickedFeature)) {
                        // clickHandler(movement);
                        return;
                    }
                    // Select the feature if it's not already selected
                    if (selected.feature === pickedFeature) {
                        return;
                    }
                    selected.feature = pickedFeature;
                    // Save the selected feature's original color
                    if (pickedFeature === highlighted.feature) {
                        Cesium.Color.clone(
                            highlighted.originalColor,
                            selected.originalColor
                        );
                        highlighted.feature = undefined;
                    } else {
                        Cesium.Color.clone(pickedFeature.color, selected.originalColor);
                    }
                    // Highlight newly selected feature
                    pickedFeature.color = Cesium.Color.LIME;
                    // Set feature infobox description
                }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
                // if (Cesium.PostProcessStageLibrary.isSilhouetteSupported(this.viewer.scene)) {
                //     var silhouetteBlue = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
                //     silhouetteBlue.uniforms.color = Cesium.Color.BLUE;
                //     silhouetteBlue.uniforms.length = 0.01;
                //     silhouetteBlue.selected = [];

                //     var silhouetteGreen = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
                //     silhouetteGreen.uniforms.color = Cesium.Color.LIME;
                //     silhouetteGreen.uniforms.length = 0.01;
                //     silhouetteGreen.selected = [];
                //     this.viewer.scene.postProcessStages.add(
                //         Cesium.PostProcessStageLibrary.createSilhouetteStage([
                //             silhouetteBlue,
                //             silhouetteGreen,
                //         ])
                //     );
                //     // 鼠标移入事件
                //     this.viewer.screenSpaceEventHandler.setInputAction(movement => {
                //         silhouetteBlue.selected = [];
                //         // Pick a new feature
                //         var pickedFeature = this.viewer.scene.pick(movement.endPosition);
                //         if (pickedFeature !== selected.feature) {
                //             silhouetteBlue.selected = [pickedFeature];
                //         }
                //     }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
                // }





                // this.viewer.zoomTo(currentModel);
                var boundingSphere = currentModel.boundingSphere;
                var cartographic = Cesium.Cartographic.fromCartesian(
                    boundingSphere.center
                );

                debugger;
                //获取模型中心点经纬度坐标
                target.maxtrixObj.lon = target.maxtrixObj.lon || (cartographic.longitude / Math.PI) * 180;
                target.maxtrixObj.lat = target.maxtrixObj.lat || (cartographic.latitude / Math.PI) * 180;
                target.maxtrixObj.ht = target.maxtrixObj.ht; //  + 30.0;
                this.update3dtilesMaxtrix(target);
                if (this.tileindex < this.activeSource.listServer.length) {
                    this.tileindex++;
                    this.activeSource.listServer[this.tileindex] && this.drawElementTiles(this.activeSource.listServer[this.tileindex])
                }
            })
            .otherwise(function (error) {
                new Error(error);
            })
    }

    addAlltiles(tilesArr) {
        if (!tilesArr || !tilesArr.length) { return }
        this.tilesLit = tilesArr.map(item => {
            item.maxtrixObj = item.maxtrixObj ? Object.assign({ ...this.maxtrixObj }, { ...item.maxtrixObj }) : this.maxtrixObj
            return item
        })
        // this.viewer.scene.globe.depthTestAgainstTerrain = true
        // 采取单独加载方式，轮询加入场景
        this.addSingletiles(this.tilesLit[this.tileindex]);
        var nameOverlay = document.createElement("div");
        this.viewer.container.appendChild(nameOverlay);
        nameOverlay.className = "backdrop";
        nameOverlay.style.display = "none";
        nameOverlay.style.position = "absolute";
        nameOverlay.style.bottom = "0";
        nameOverlay.style.left = "0";
        nameOverlay.style["pointer-events"] = "none";
        nameOverlay.style.padding = "4px";
        nameOverlay.style.backgroundColor = "black";
        nameOverlay.style.color = "while";
        var selected = {
            feature: undefined,
            originalColor: new Cesium.Color(),
        };
        var selectedEntity = new Cesium.Entity();
        var highlighted = {
            feature: undefined,
            originalColor: new Cesium.Color(),
        };
        // var initialPosition = Cesium.Cartesian3.fromDegrees(
        //     -74.01881302800248,
        //     40.69114333714821,
        //     753
        //   );
        //   var initialOrientation = new Cesium.HeadingPitchRoll.fromDegrees(
        //     21.27879878293835,
        //     -21.34390550872461,
        //     0.0716951918898415
        //   );
        //   this.viewer.scene.camera.setView({
        //     destination: initialPosition,
        //     orientation: initialOrientation,
        //     endTransform: Cesium.Matrix4.IDENTITY,
        //   });
        this.viewer.screenSpaceEventHandler.setInputAction(movement => {
            // If a feature was previously selected, undo the highlight
            if (Cesium.defined(selected.feature)) {
                selected.feature.color = selected.originalColor;
                selected.feature = undefined;
            }
            // Pick a new feature
            var pickedFeature = this.viewer.scene.pick(movement.position);
            if (!Cesium.defined(pickedFeature)) {
                // clickHandler(movement);
                return;
            }
            // Select the feature if it's not already selected
            if (selected.feature === pickedFeature) {
                return;
            }
            selected.feature = pickedFeature;
            // Save the selected feature's original color
            if (pickedFeature === highlighted.feature) {
                Cesium.Color.clone(
                    highlighted.originalColor,
                    selected.originalColor
                );
                highlighted.feature = undefined;
            } else {
                Cesium.Color.clone(pickedFeature.color, selected.originalColor);
            }
            // Highlight newly selected feature
            pickedFeature.color = Cesium.Color.LIME;
            // Set feature infobox description
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
        // if (Cesium.PostProcessStageLibrary.isSilhouetteSupported(this.viewer.scene)) {
        //     // Silhouettes are supported
        //     var silhouetteBlue = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
        //     silhouetteBlue.uniforms.color = Cesium.Color.BLUE;
        //     silhouetteBlue.uniforms.length = 0.01;
        //     silhouetteBlue.selected = [];

        //     var silhouetteGreen = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
        //     silhouetteGreen.uniforms.color = Cesium.Color.LIME;
        //     silhouetteGreen.uniforms.length = 0.01;
        //     silhouetteGreen.selected = [];
        //     this.viewer.scene.postProcessStages.add(
        //         Cesium.PostProcessStageLibrary.createSilhouetteStage([
        //             silhouetteBlue,
        //             silhouetteGreen,
        //         ])
        //     );
        //     // 鼠标移入事件
        //     // this.viewer.screenSpaceEventHandler.setInputAction(movement => {
        //     //     silhouetteBlue.selected = [];
        //     //     // Pick a new feature
        //     //     var pickedFeature = this.viewer.scene.pick(movement.endPosition);
        //     //     if (!Cesium.defined(pickedFeature)) {
        //     //         nameOverlay.style.display = "none";
        //     //         return;
        //     //     }
        //     //     // A feature was picked, so show it's overlay content
        //     //     nameOverlay.style.display = "block";
        //     //     nameOverlay.style.bottom =
        //     //         this.viewer.canvas.clientHeight - movement.endPosition.y + "px";
        //     //     nameOverlay.style.left = movement.endPosition.x + "px";
        //     //     // var name = pickedFeature.getProperty("BIN");
        //     //     nameOverlay.textContent = 'dfefece';
        //     //     if (pickedFeature !== selected.feature) {
        //     //         silhouetteBlue.selected = [pickedFeature];
        //     //     }
        //     // }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

        //     this.viewer.screenSpaceEventHandler.setInputAction(movement => {
        //         // var pickedFeature = this.viewer.scene.pick(movement.position);
        //         // If a feature was previously selected, undo the highlight
        //         silhouetteGreen.selected = [];
        //         // Pick a new feature
        //         var pickedFeature = this.viewer.scene.pick(movement.position);
        //         // Select the feature if it's not already selected
        //         if (silhouetteGreen.selected[0] === pickedFeature) {
        //             return;
        //         }
        //         // Save the selected feature's original color
        //         var highlightedFeature = silhouetteBlue.selected[0];
        //         if (pickedFeature === highlightedFeature) {
        //             silhouetteBlue.selected = [];
        //         }
        //         // Highlight newly selected feature
        //         silhouetteGreen.selected = [pickedFeature];
        //     }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
        // }
    }
    addSingletiles(titleobj) {
        debugger
        titleobj.tileModel = this.viewer.scene.primitives.add(
            new Cesium.Cesium3DTileset({
                url: titleobj.tileUrl,// Cesium.IonResource.fromAssetId(75343), //  
                skipLevelOfDetail: true,
                baseScreenSpaceError: 512,
                skipScreenSpaceErrorFactor: 32,
                skipLevels: 1,
                immediatelyLoadDesiredLevelOfDetail: false,
                loadSiblings: false,
                cullWithChildrenBounds: true,
                dynamicScreenSpaceError: true,
                maximumScreenSpaceError: 32,
                backFaceCulling: true
            })
        )
        this.managerCollection.add(titleobj.tileModel);
        this.viewer.scene.primitives.add(this.managerCollection);
        titleobj.tileModel.readyPromise
            .then((currentModel) => {

                debugger
                titleobj.currentModel = currentModel
                var scene = this.viewer.scene;
                this.viewer.zoomTo(currentModel);
                var boundingSphere = currentModel.boundingSphere;
                var cartographic = Cesium.Cartographic.fromCartesian(
                    boundingSphere.center
                );
                //获取模型中心点经纬度坐标
                titleobj.maxtrixObj.lon = titleobj.maxtrixObj.lon || (cartographic.longitude / Math.PI) * 180;
                titleobj.maxtrixObj.lat = titleobj.maxtrixObj.lat || (cartographic.latitude / Math.PI) * 180;
                titleobj.maxtrixObj.ht = titleobj.maxtrixObj.ht || cartographic.height + 30.0;

                this.update3dtilesMaxtrix(titleobj);
                // if (this.tileindex < this.tilesLit.length) {
                //     this.tileindex++;
                //     this.addSingletiles(this.tilesLit[this.tileindex])
                // }
            })
            .otherwise(function (error) {
                new Error(error);
            })
    }
    destorySingletiles() { }
    destoryAlltiles() {
        if (this.tilesLit.length === 0) { return };
        this.managerCollection.destroyPrimitives = false
        this.tilesLit.forEach((item, index) => {
            if (index >= 1) {
                return
            }
            if (!item.tileModel.isDestroyed()) {
                item.tileModel.show = false;
                const t = this.managerCollection.remove(item.tileModel);
                this.managerCollection.destroy(item.tileModel);
            }
        })
    }
    setParameter() { }
    // 调整模型位置
    update3dtilesMaxtrix(titleobj) {
        var mx = Cesium.Matrix3.fromRotationX(
            Cesium.Math.toRadians(titleobj.maxtrixObj.rx || 0)
        );
        var my = Cesium.Matrix3.fromRotationY(
            Cesium.Math.toRadians(titleobj.maxtrixObj.ry || 0)
        );
        var mz = Cesium.Matrix3.fromRotationZ(
            Cesium.Math.toRadians(titleobj.maxtrixObj.rz || 0)
        );
        var rotationX = Cesium.Matrix4.fromRotationTranslation(mx);
        var rotationY = Cesium.Matrix4.fromRotationTranslation(my);
        var rotationZ = Cesium.Matrix4.fromRotationTranslation(mz);
        //平移 修改经纬度
        var position = Cesium.Cartesian3.fromDegrees(
            titleobj.maxtrixObj.lon,
            titleobj.maxtrixObj.lat,
            titleobj.maxtrixObj.ht
        );
        var m = Cesium.Transforms.eastNorthUpToFixedFrame(position);
        //旋转、平移矩阵相乘
        Cesium.Matrix4.multiply(m, rotationX, m);
        Cesium.Matrix4.multiply(m, rotationY, m);
        Cesium.Matrix4.multiply(m, rotationZ, m);
        //缩放 修改缩放比例
        var scale = Cesium.Matrix4.fromUniformScale(titleobj.maxtrixObj.sc);
        Cesium.Matrix4.multiply(m, scale, m);
        //赋值给tileset
        titleobj.tileModel._root.transform = m;
        //调整地下透明度
        // this.viewer.scene.globe.translucency.frontFaceAlphaByDistance.nearValue = Cesium.Math.clamp(
        //     titleobj.maxtrixObj.ap,
        //     0.0,
        //     1.0
        // );
    }

    // 从集合中删除基本体
    removePrimitive(name) {
        this.activeSource = CesiumDX.DXSourceOptions.EleOptions.find(ele => ele.name === name) || null;
        this.activeSource.listServer.forEach(item => {
            const a = this.viewer.scene.primitives.remove(item.tileModel)
        })
        this.tileindex = 0
        this.activeSource.listServer = []
    }
    removePrimitiveList() {
        // this.tilesLit.forEach(item => {
        //     this.viewer.scene.primitives.remove(item.tileModel)
        // });
    }
    removePrimitiveData(data) {
        data.tileModel && this.viewer.scene.primitives.remove(data.tileModel)
    }


}